package com.atguigu.java3;

import com.atguigu.java1.Person;
import org.junit.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * @author yihu
 * @create 2021-06-17 10:59
 * @email:1057202547@qq.com
 * @dec: 调用运行时类中指定的结构:属性 方法 构造器
 */
public class ReflectionTest {
    @Test
    public void testFild() throws  Exception{
        Class<Person> clazz = Person.class;
        //创建运行时类的对象
        Person person = clazz.newInstance();

        //获取指定属性(public权限的属性)
        //通常不采用此方法  // clazz.getDeclaredField()
        Field id = clazz.getField("id");

        //设置当前属性的值
        /**
         * set 参数
         * 1： 指明设置哪个对象的属性
         * 2： 设置成多少
         */
        id.set(person,1001);
        //获取当前属性值
        /**
         * get 参数
         * 获取哪个对象的属性值
         */
         int pid = (int) id.get(person);
         System.out.println(pid);
    }

    @Test
    public void testFild1() throws  Exception{
        Class<Person> clazz = Person.class;
        //创建运行时类的对象
        Person person = clazz.newInstance();

        //获取属性 getDeclaredField(String fieldName):获取运行时类中指定变量名的属性
        Field name = clazz.getDeclaredField("name");
        //2.保证当前属性是可访问的
        name.setAccessible(true);
        //3.获取、设置指定对象的此属性值
        name.set(person,"Tom");

        System.out.println(name.get(person));
    }

     /*
      如何操作运行时类中的指定的方法 -- 需要掌握
     */
     @Test
     public void testMethod() throws Exception {
         Class<Person> clazz = Person.class;
         //创建运行时类的对象
         Person person = clazz.newInstance();
         /*
            1.获取指定的某个方法
            getDeclaredMethod():参数1 ：指明获取的方法的名称  参数2：指明获取的方法的形参列表
         */
         Method show = clazz.getDeclaredMethod("show", String.class);
         //2.保证当前属性是可访问的
         show.setAccessible(true);
         /*
            3. 调用方法的invoke():
            参数1：方法的调用者  参数2：给方法形参赋值的实参
            invoke()的返回值即为对应类中调用的方法的返回值。
         */
         String value = (String) show.invoke(person, "中国");
         System.out.println(value);

         System.out.println("*************如何调用静态方法*****************");
         // private static void showDesc()
         Method showDesc = clazz.getDeclaredMethod("showDesc");
         showDesc.setAccessible(true);
         //如果调用的运行时类中的方法没有返回值，则此invoke()返回null
         Object returnValue = showDesc.invoke(clazz);
         System.out.println(returnValue);
     }
     /*
       如何调用运行时类中的指定的构造器
     */
     @Test
     public void testConstructor() throws Exception {
         Class<Person> clazz = Person.class;
         //private Person(String name)
        /*
            1.获取指定的构造器
            getDeclaredConstructor():参数：指明构造器的参数列表
         */
         Constructor<Person> constructor = clazz.getDeclaredConstructor(String.class);
         //2.保证此构造器是可访问的
         constructor.setAccessible(true);
         //3.调用此构造器创建运行时类的对象
         Person p = constructor.newInstance("TOM");

         System.out.println(p);

     }
}
